.TITLE DXDRV .IDENT /06.02/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; H. J. LEV 16-JAN-75 ; P. J. BEZEREDI ; P. J. CARR ; ; MODIFIED BY: ; ; G. MARIGOWDA 4-AUG-86 V06.02 ; GM001 -- CONVERT TO USE EXEC VECTORING ; ; ; RX01 - RX11 FLOPPY DISK DRIVER ; ; FUNCTIONS RECOGNIZED: ; IO.RPB - READ PHYSICAL BLOCK (MAY READ ANY SECTOR ON DISK) ; IO.WPB - WRITE PHYSICAL BLOCK (MAY WRITE ANY SECTOR ON DISK) ; IO.WDD - WRITE DELETED DATA - WRITE ANY SECTOR ON DISK ; SETTING THE DELETED DATA MARK IN SECTOR HEADER ; THE FOLLOWING TWO FUNCTION CODES OPERATE ON 256 WORD BLOCKS ; OF DATA (4 SECTORS) THE DRIVER AUTOMATICALLY INTERLEAVES ; AND SKEWS SECTORS TO OPTIMIZE THE TRANSFER OF DATA ; SO THAT A LONG READ/WRITE MAY BE DONE WITHOUT LOOSING ; A REVOLUTION OF THE DISK. THE INTERLEAVE FACTOR IS 2 ; AND THE SKEW FACTOR IS 6. ; IO.RLB - READ LOGICAL BLOCKS OF 256. WORDS ; IO.WLB - WRITE LOGICAL BLOCKS OF 256. WORDS. ; ; IF DELETED DATA IS READ, THE STATUS CODE RETURNED WILL ; BE IS.RDD, OTHERWISE IT IS IS.SUC ; .MCALL HWDDF$,PKTDF$,QIOSY$,SCBDF$ HWDDF$ ; DEFINE HARDWARE REGISTERS PKTDF$ ; DEFINE I/O PACKET OFFSETS QIOSY$ SCBDF$ ,,SYSDEF ; ; EQUATED SYMBOLS ; RETRY = 8. ; ERROR RETRY COUNT DXNUM = 4 ; NUMBER OF REGISTERS TO ERROR LOG ; ; RX11 DEVICE REGISTER OFFSETS AND BIT DEFINITIONS ; RXCS = 0 ; CONTROL STATUS REGISTER RXDB = 2 ; DATA BUFFER UNIT = 20 ; UNIT SELECT BIT DONE = 40 ; RX11 DONE INTEBL = 100 ; INTERRUPT ENABLE TR = 200 ; RX11 TRANSFER READY BIT (CPU-SILO) INIT = 40000 ; INITIALIZE RX11 ; ; FUNCTION CODES ; GO = 1 ; GO BIT FILL = 0+GO ; FILL SILO EMPTY = 2+GO ; EMPTY SILO WRITE = 4+GO ; WRITE A SECTOR READ = 6+GO ; READ A SECTOR RDSTS = 12+GO ; READ STATUS WRTDD = 14+GO ; WRITE DELETED DATA RDERC = 16+GO ; READ ERROR CODE ; ; STATUS REGISTER BIT DEFINITIONS ; DD = 100 ; DELETED DATA READ RDY = 200 ; UNIT READY ; ; LOCAL DATA ; ; ; CONTROLLER TABLE AND RETRY COUNT TABLE ( INDEXED BY CONTROLLER NUMBER) ; RTTBL: .BLKW R$$X11 ; ERROR RETRY COUNT FOR CURRENT UNIT CSRSV: .BLKW R$$X11 ; CSR SAVE AREA ; ; MAKE GTPKT$ A LOCAL MACRO ; .MACRO GTPKT$ DEV,NCTRLR,ADDR,UCBSV,SUC CALL @GTPKT .IF B BCC 65535$ RETURN 65535$: .IFF BCS ADDR .ENDC .IF B $$$=0 .IF B .IF EQ $$$ MOV R5,S.OWN(R4) .ENDC .ENDC .IFF .IF GT NCTRLR-1 MOV R5,UCBSV(R3) .IFF MOV R5,UCBSV .ENDC .ENDC .ENDM ; ; EXECUTIVE ENTRY POINT VECTOR TABLE ; EXEVEC: .WORD 0 ; FLAG FOR VECTOR NOT YET FILLED ALOCB: .WORD $ALOCB BMSET: .WORD $BMSET DEACB: .WORD $DEACB DTOER: .WORD $DTOER DVERR: .WORD $DVERR ERRSQ: .WORD $ERRSQ FORK: .WORD $FORK GTPKT: .WORD $GTPKT IODON: .WORD $IODON VOLVD: .WORD $VOLVD ; KISR6: .WORD KISAR6 ; EXEVCL=<<<.-EXEVEC>/2>-1> ; ; ; DRIVER DISPATCH TABLE ; DDT$ DX,R$$X11,,,,NEW ;GENERATE DISPATCH TABLE ;+ ; *** - DXINI FLOPPY DISK CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QIO DIRECTIVE WHEN AN I/O REQUEST ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPOGATE THE ; EXECUTION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, ; THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST. OTHERWISE ; A RETURN TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESS ; THE NEXT I/O OPERATION IS INITIATED. A RETURN TO THE CALLER IS THEN ; EXECUTED. ; ; INPUTS: ; R5 - ADDRESS OF UCB WHICH IS ASSOCIATED WITH CONTROLLER TO BE IN ; ; OUTPUTS: ; IF THE CONTROLLER ASSOCIATED WITH THE SPECIFIED UCB IS NOT ; BUSY AND AN I/O REQUEST IS WAITING TO BE PROCESSED, THE REQUEST ; IS DEQUEUED AND THE DRIVER INITIATES THE REQUESTED FUNCTION. ; ;- .ENABL LSB DXINI: GTPKT$ DX,R$$X11 ; GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT ; ; R1 - ADDRESS OF THE I/O PACKET ; R2 - PHYSICAL UNIT NUMBER OF THE DEVICE TO PERFORM FUNCTION ON ; R3 - CONTROLLER NUMBER MULTIPLIED BY TWO ; R4 - ADDRESS OF SCB ; R5 - ADDRESS OF UCB FOR DEVICE TO PERFORM FUNCTION ON ; ; RX11 FLOPPY DISK I/O REQUEST PACKET FORMAT ; ; WD. 00 -- I/O QUEUE THREAD WORD ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER ; WD. 02 -- ADDRESS OF TCB OF THE REQUESTING TASK ; WD. 03 -- POINTER TO SECOND LUN WORD OF REQUESTING TASKS HEADER ; WD. 04 -- CONTENTS OF FIRST LUN WORD ( UCB ADDRESS) ; WD. 05 -- I/O FUNCTION CODE (IO.RLB, IO.RPB, IO.WLB, OR IO.WPB) ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE ; WD. 12 -- RELOCATION BIAS OF DATA BUFFER ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER ; WD. 14 -- NUMBER OF BYTES TO TRANSFER ; WD. 15 -- NOT USED (IGNORED) ; WD. 16 -- LOW BYTE MUST BE ZERO, HIGH BYTE NOT USED ; WD. 17 -- LOGICAL OR PHYSICAL BLOCK NUMBER ; WD. 20 -- NOT USED ; ; DRIVER USAGE OF WORDS IN I/O PACKET ; I.PRM+6 (WD. 15) - STATUS REGISTER AFTER INTERRUPT ; I.PRM+10 (WD. 16) - LOGICAL OR PHYSICAL SECTOR NUMBER ; I.PRM+12 (WD. 17) - SIZE OF "THIS" TRANSFER ; I.PRM+14 (WD. 20) - PHYSICAL SECTOR NUMBER (1-26.) ; I.PRM+15 (WD. 20) - PHYSICAL TRACK NUMBER (0-77.) ; ; ; INITIALIZE DRIVER ; 10$: MOV #RETRY,RTTBL(R3) ; SET RETRY COUNT CALL @VOLVD ; VALIDATE VOLUME VALID BCS 16$ ; IF CS WE FAILED TST R0 ; TRANSFER FUNCTION? BPL 16$ ; IF PL NO TSTB I.PRM+10(R1) ; HIGH BLOCK SPECIFIED? BEQ 20$ ; NO 15$: JMP 180$ ; YES, ERROR 16$: JMP 210$ ; EXIT ; ; SET UP FIRST BLOCK OR SECTOR NUMBER ; 20$: MOV I.PRM+12(R1),R0 ; GET PHYSICAL OR LOGICAL BLOCK NUMBER MOV #128.,I.PRM+12(R1) ; PRESET TRANSFER SIZE BITB #IO.RPB&377,I.FCN(R1) ; PHYSICAL BLOCK FUNCTION? BNE 30$ ; YES ASL R0 ; CONVERT TO LOGICAL SECTOR NUMBER ASL R0 ; WHICH IS LBN*4 30$: MOV R0,I.PRM+10(R1) ; STORE IT MOV #RDSTS,R0 ; GET READ STATUS FUNCTION TSTB U.UNIT(R5) ; UNIT 1? BEQ 31$ ; IF EQ NO BIS #UNIT,R0 ; YES, SET UNIT SELECT BIT 31$: MOVB S.CON(R4),R3 ; RETREIVE CONTROLLER INDEX MOV R0,CSRSV(R3) ; SAVE THIS FUNCTION MOVB #2,RTTBL+1(R3) ; FLAG THE GET STATUS MOV S.CSR(R4),R2 ; RETREIVE CSR ADDRESS MOV R0,(R2) ; DO THE GET STATUS JMP 155$ ; START THE FUNCTION 32$: MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS BIT #RDY,I.PRM+6(R1); IS THE UNIT READY? BNE 35$ ; IF NE YES 33$: CALL LOGERR ; LOG UNIT NOT READY MOV #IE.DNR&377,R0 ; SET UNIT NOT READY ERROR CODE JMP 200$ ; GOOD-BYE! 35$: MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS CALL TRKSEC ; CONVERT BLOCK # TO TRACK/SECTOR BCS 15$ ; IF CS BAD BLOCK NUMBER MOV S.CSR(R4),R2 ; GET ADDRESS OF CSR CMPB #IO.WLB/256.,I.FCN+1(R3) ; WRITE FUNCTION? BNE 140$ ;IF NE NO ; ; FILL SILO BEFORE WRITE ; CALL SETBUF ; SET UP BUFFER POINTER AND MAPPING REGI MOV #FILL,(R2) ; SET "FILL BUFFER" FUNCTION 70$: CLR R3 ; ASSUME NO DATA TO TRANSFER DEC R1 ; MORE DATA TO TRANSFER? BLT 74$ ; NO MOVB (R0)+,R3 ; YES, GET NEXT BYTE 74$: BITB #TR!DONE,(R2) ; CONTROLLER DONE? BMI 75$ ; IF MI YES BEQ 74$ ; IF EQ NO BR 90$ ; SILO IS FULL 75$: MOVB R3,RXDB(R2) ; PUT NEXT BYTE IN SILO BR 70$ ; AND WAIT TILL IT'S ACCEPTED 90$: TST R1 ; ALL BYTES TRANSFERED? BMI 130$ ; IF MI YES 95$: JMP DXRTY ; RETRY LAST FUNCTION ; ; EMPTY SILO AFTER READ ; 100$: MOV #EMPTY,(R2) ; SET "EMPTY BUFFER" FUNCTION CALL SETBUF ; SET BUFFER POINTER AND MAPPING REGISTE 110$: BITB #TR!DONE,(R2) ; CONTROLLER DONE? BMI 111$ ; IF MI YES BEQ 110$ ; IF EQ NO BR 120$ ; SILO IS EMPTY 111$: MOVB RXDB(R2),R3 ; GET NEXT BYTE FROM SILO DEC R1 ; DO WE WANT IT? BLT 110$ ; NO MOVB R3,(R0)+ ; YES, PUT IT IN BUFFER BR 110$ ; GET NEXT BYTE 120$: TST R1 ; ALL BYTES TRANSFERED? BGT 95$ ; IF GT ERROR MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS CALL NXTSEC ; UPDATE TO NEXT SECTOR BNE 35$ ; IF NE CONTINUE JMP 193$ ; FINISHED ; ; INITIATE TRANSFER BETWEEN SILO AND DISK ; 130$: MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS MOV #WRITE,R0 ; ASSUME WRITE FUNCTION MOV I.FCN(R3),R1 ; COPY FUNCTION CODE BIC #7,R1 ; REMOVE QUALIFIER BITS CMP #IO.WDD,R1 ; WRITE DELETED DATA? BNE 141$ ; IF NE NO MOV #WRTDD,R0 ; SET "WRITE DELETED DATA" FUNCTION BR 141$ ; 140$: MOV #READ,R0 ; SET READ FUNCTION 141$: TSTB U.UNIT(R5) ; UNIT 1? BEQ 142$ ; IF EQ YES BIS #UNIT,R0 ; YES, SET TO SELECT UNIT 1 142$: MOVB S.CON(R4),R1 ; RETREIVE CONTROLLER INDEX MOV R0,CSRSV(R1) ; SAVE FUNCTION AND UNIT NUMBER CLRB RTTBL+1(R1) ; RESET FLAGS MOV R0,(R2) ; INITIATE THE FUNCTION 143$: BITB #TR!DONE,(R2) ; TRANSFER READY OR DONE? BMI 150$ ; IF MI TRANSFER READY BEQ 143$ ; IF EQ LOOP BR 95$ ; ERROR, NO TRANSFER REQUEST 150$: MOVB I.PRM+14(R3),RXDB(R2) ; LOAD SECTOR NUMBER 151$: BITB #TR!DONE,(R2) ; TRANSFER READY OR DONE? BMI 152$ ; IF MI TRANSFER READY BEQ 151$ ; IF EQ LOOP BR 95$ ; ERROR, NO TRANSFER REQUEST 152$: MOVB I.PRM+15(R3),RXDB(R2) ; LOAD TRACK NUMBER 155$: MOVB S.ITM(R4),S.CTM(R4) ; SET TIME OUT COUNT CALL @BMSET ;SET I/O ACTIVE IN BITMAP BIS #INTEBL,(R2) ;;; SET INTERRUPT ENABLE ;+ ; DXKRB-CONTROLLER ONLINE/OFFLINE ROUTINE ; ;- DXKRB: BCS 2$ ;IF CS OFFLINE REQUEST TST EXEVEC ;IF ALREADY DONE BNE 2$ ;SKIP THIS MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV KINAR6,-(SP) ;SAVE KINAR6 MOV @#112,R0 ;GET ADDRESS OF TABLE OF ENTRIES MOV (R0),R0 ;GET ADDRESS OF APR BIAS (1ST WORD IN TABLE) MOV (R0),KINAR6 ;MAP COMMON THROUGH I-SPACE APR6 MOV #EXEVEC,R3 ;POINT TO VECTOR MOV #EXEVCL,R2 ;SPECIFY LENGTH OF VECTOR CALL @#140004 ;TRANSLATE THE VECTOR MOV (SP)+,KINAR6 ;RESTORE KINAR6 MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ;RESTORE R2 2$: RETURN ; DXPWF - POWER FAIL ENTRY POINT ; POWER FAIL IS HANDLED BY THE DEVICE TIMING OUT, THEREFORE ; NO WNRK IS DNNE HERE. IT WILL BE HANDLED WHEN THE DEVICE ; TIME OUT ENTRY IS EXECUTED. ; DXPWF: ; ; UNIT STATUS CHANGE ROUTINE DXUCB: ; ; DXCAN - CANCEL I/O ENTRY POINT ; CANCEL I/O IS A NOP OP FOR FILE STRUCTURED DEVICES ; DXCAN: RETURN ; ;+ ; *** - $DXINT - RX11 FLOPPY DISK INTERRUPT ENTRY POINT ; ;- INTSE$ DX,PR5,R$$X11 ;;; GENERATE INTERRUPT SAVE CODE MOV R3,-(SP) ;;; SAVE REGISTER MOV U.SCB(R5),R4 ;;; GET SCB ADDRESS MOV S.PKT(R4),R3 ;;; GET I/O PACKET ADDRESS MOV S.CSR(R4),R4 ;;; GET CSR ADDRESS MOV RXDB(R4),I.PRM+6(R3) ;;; SAVE CONTROLLER STATUS MOV (SP)+,R3 ;;; RESTORE REGISTER BIC #INTEBL,(R4) ;;; DISABLE INTERRUPTS CALL @FORK ;;; CREATE A SYSTEM PROCESS MOV R4,R2 ; COPY CSR ADDRESS MOV U.SCB(R5),R4 ; GET SCB ADDRESS MOVB S.CON(R4),R3 ; GET CONTROLLER INDEX TST (R2) ; ANY ERRORS? BPL 160$ ; IF PL NO BITB #2,RTTBL+1(R3) ; GET STATUS FUNCTION? BEQ 156$ ; IF EQ NO JMP 33$ ; DRIVE NOT READY 156$: CALL LOGERR ; LOG DEVICE ERROR BR DXRTY ; RETRY FUNCTION 160$: BITB #1,RTTBL+1(R3) ; INITIALIZE IN PROGRESS? BNE 170$ ; IF NE YES BITB #2,RTTBL+1(R3) ; GET STATUS FUNCTION? BEQ 161$ ; IF EQ NO JMP 32$ ; TEST IF UNIT IS READY 161$: MOV S.PKT(R4),R3 ; RETREIVE I/O PACKET ADDRESS CMPB #IO.RLB/256.,I.FCN+1(R3) ; READ? BNE 165$ ; IF NE NO JMP 100$ ; GO EMPTY SILO 165$: CALL NXTSEC ; UPDATE TO NEXT SECTOR BEQ 195$ ; ALL DONE 170$: JMP 35$ ; WRITE MORE DATA 180$: MOV #IE.BLK&377,R0 ; SET BAD BLOCK ERROR BR 210$ ; 190$: MOV #IE.VER&377,R0 ; SET UNRECOVERABLE ERROR BR 200$ ; 193$: BITB #IO.RPB&377,I.FCN(R3) ; READ PHYSICAL BLOCK FUNCTION? BEQ 195$ ; NO, THEN IGNORE DELETED DATA MARK MOV #IS.RDD&377,R0 ; YES, DEFAULT ON READ TO DELETED DATA BIT #DD,I.PRM+6(R3) ; WAS DELETED DATA READ? BNE 200$ ; YES 195$: MOV #IS.SUC&377,R0 ; NO, SET NORMAL SUCCESS 200$: MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS MOV I.PRM+4(R1),R1 ; SET BYTES TRANSFERED SUB U.CNT(R5),R1 ; CALCULATE BYTES ACTUALLY TRANSFERED MOVB S.CON(R4),R3 ; RETREIVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ; SET FINAL RETRY COUNT BIS #RETRY*256.,R2 ; SET INITIAL RETRY COUNT 210$: CALL @IODON ; SET DONE JMP DXINI ; TRY FOR ANOTHER REQUEST ; ;+ ; *** - DXOUT - FLOPPY DISK TIMEOUT ENTRY POINT ;- DXOUT: CALL LOGTMO ;;; LOG DEVICE TIMEOUT ; ; RETRY LAST FUNCTION ; DXRTY: MOVB S.CON(R4),R3 ; RESTORE CONTROLLER INDEX MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS BITB #IQ.X,I.FCN(R1) ; INHIBIT RETRIES? BNE 190$ ; IF NE YES DECB RTTBL(R3) ; ANY RETRIES LEFT? BEQ 190$ ; NO, ERROR MOVB #1,RTTBL+1(R3) ; YES, SET INITIALIZE IN PROGRESS MOV #INIT,CSRSV(R3) ; SAVE FUNCTION CODE MOV #INIT,(R2) ; INITIALIZE RX01 DRIVES JMP 155$ ; AND DO IT .DSABL LSB ;+ ; **-LOGERR-LOG DEVICE ERROR ; **-LOGTMO-LOG DEVICE TIMEOUT ; ; THESE ROUTINES WILL ALLOCATE A CORE BLOCK, FILL IT WITH THE ; REGISTER INFORMATION, CALL THE APPROPRIATE EXECUTIVE ERROR ; LOGGING ROUTINE, DEALLOCATE THE CORE BLOCK, AND RETURN BACK TO ; THE CALLER. ; ; INPUTS: ; R3=CONTROLLER INDEX ; R4=SCB ADDRESS ; R5=UCB ADDRESS ; ; OUTPUTS: ; R2=CSR ADDRESS ; R4=SCB ADDRESS ; R5=UCB ADDRESS ; ; R0, R1 AND R3 ARE DESTROYED. ;- .ENABL LSB LOGERR: MOV DVERR,-(SP) ; LOG DEVICE ERROR BR 10$ ; LOGTMO: MOV DTOER,-(SP) ;;; LOG DEVICE TIMEOUT 10$: MOV #DXNUM*2,R1 ; GET NUMBER OF BYTES TO ALLOCATE CALL @ALOCB ; ALLOCATE THE ERROR BLOCK BCC 20$ ; IF CC OK INC @ERRSQ ; INDICATE A MISSED ERRO CMP (SP)+,DTOER ; TIMEOUT? BNE 30$ ; IF NE NO BIC #INTEBL,@S.CSR(R4) ;;; CLEAR INTERRUPT ENABLE MTPS #0 ;;; ALLOW INTERRUPTS BR 30$ ; 20$: MOV R0,R1 ; COPY CORE BLOCK ADDRESS MOV S.CSR(R4),R2 ; RETREIVE CSR ADDRESS MOV (R2),(R1) ; SAVE CSR CONTENTS BIS CSRSV(R3),(R1)+ ; SET BITS 0-4 IN RXCS MOV RXDB(R2),(R1)+ ; SAVE RXDB MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS MOV I.PRM+6(R3),(R1)+ ; SAVE RXES MOV #RDERC,(R2) ; EXECUTE READ ERROR CODE FUNCTION 25$: BITB #DONE,(R2) ; WAIT UNTIL DONE BEQ 25$ ; IF EQ NO MOV RXDB(R2),(R1) ; SAVE RXER MOV R0,R2 ; GET CORE BLOCK ADDRESS CALL @(SP)+ ; LOG THE ERROR MOV R2,R0 ; GET BACK CORE BLOCK ADDRESS MOV #DXNUM*2,R1 ; GET NUMBER OF BYTES TO DEALLOCATE CALL @DEACB ; DEALLOCATE THE ERROR BLOCK 30$: MOV S.CSR(R4),R2 ; RETREIVE CSR ADDRESS RETURN ; .DSABL LSB ;+ ; *** - TRKSEC - CONVERT LOGICAL OR PHYSICAL BLOCK NUMBER TO ; TRACK-SECTOR PAIR ; FROM ALGORITHM BY J GILBERT MODIFIED BY H. JACOBS ; ; INPUT: ; R3 - I/O PACKET ADDRESS ; I.PRM+10(R3) - LOGICAL OR PHYSICAL SECTOR ; ; OUTPUT: ; I.PRM+14(R3) - SECTOR (1-26.) ; I.PRM+15(R3) - TRACK (0-77.) ; R3 - UNCHANGED ; C CLEAR - VALID BLOCK ; C SET - BAD BLOCK NUMBER (PHYSICAL OR LOGICAL) ; ;- TRKSEC: MOV I.PRM+10(R3),R1 ; GET LOGICAL OR PHYSICAL BLOCK MOV #8.,R0 ; SET LOOP COUNT MOV #6400,R2 ; SET DIVISOR 1$: CMP R2,R1 ; DOES 26 GO INTO DIVIDEND? BHI 2$ ; BRANCH IF NOT, C CLEAR SUB R2,R1 ; SUBTRACT 26 FROM DIVIDEND SEC ; SET CARRY 2$: ROL R1 ; SHIFT DIVIDEND AND QUOTIENT DEC R0 ; DONE? BGT 1$ ; NO, LOOP MOVB R1,R0 ; GET TRACK NUMBER CLRB R1 ; CLEAR TRACK NUMBER SWAB R1 ; SHIFT DONE SECTOR NUMBER BITB #IO.RPB&377,I.FCN(R3) ; PHYSICAL BLOCK WANTED? BNE 10$ ; YES CMP #12.,R1 ; NO, C=1 IF 13<=R1<=25 ROL R1 ; DOUBLE FOR INTERLEAVE FACTOR ASL R0 ; ADD TRACK -TRACK SKEW ADD R0,R1 ; SKEW BY 2*TRACK ADD R0,R1 ; SKEW BY 4*TRACK ADD R0,R1 ; SKEW BY 6*TRACK ASR R0 ; RESTORE TRACK NUMBER MOV #26.,R2 ; SET MODULUS 5$: SUB R2,R1 ; MODULO SECTOR INTO RANGE -26. TO -1. BGE 5$ ; LOOP TILL REMAINDER GOES NEG ADD R2,R1 ; CONVERT TO RANGE 0-25. INC R0 ; LBN0 STARTS ON TRACK 1 10$: INC R1 ; CONVERT TO RANGE 1-26. MOV R1,I.PRM+14(R3) ; SAVE SECTOR NUMBER MOVB R0,I.PRM+15(R3) ; SAVE TRACK NUMBER CMP #77.*256.,I.PRM+14(R3) ; IS IT A VALID TRACK/SECTOR? RETURN ; ;+ ; *** - NXTSEC - UPDATE BLOCK NUMBER , BUFFER ADDRESS ; AND BUFFER POINTER ; ; INPUT: ; R3 - I/O PACKET ADDRESS ; R5 - UCB ADDRESS ; I.PRM+10(R3) - CURRENT BLOCK NUMBER ; I.PRM+12(R3) - BYTES TRANSFERED DURING LAST FUNCTION ; U.CNT(R5) - BYTES LEFT TO TRANSFER ; U.BUF(R5) - BUFFER ADDRESS ; ; OUTPUT: ; I.PRM+10(R3) - UPDATED BLOCK NUMBER ; U.BUF(R5) - UPDATED BY 128. BYTES ; U.CNT(R5) - UPDATED BY NUMBER OF WORDS TRANSFERED ; Z SET - ALL BYTES TRANSFERED ; Z CLEAR - MORE BYTES TO TRANSFER ; C CLEAR - VALID TRACK/SECTOR ; C SET - BAD BLOCK NUMBER ; ;+ NXTSEC: INC I.PRM+10(R3) ; UPDATE BLOCK NUMBER ADD #2,U.BUF(R5) ; UPDATE MEMORY BLOCK NUMBER SUB I.PRM+12(R3),U.CNT(R5) ; UPDATE BYTES LEFT TO TRANSFER RETURN ; ;+ ; *** - SETBUF - SET UP BUFFER POINTER FOR CPU - SILO TRANSFERS ; ; INPUT: ; R3 - I/O PACKET ADDRESS ; R5 - UCB ADDRESS ; ; OUTPUT: ; I.PRM+12(R3) - BYTES TO TRANSFER ; R0 - BUFFER ADDRESS ; R1 - BYTES TO TRANSFER ; ;- SETBUF: MOV U.BUF+2(R5),R0 ; GET BUFFER ADDRESS MOV #128.,R1 ; DEFAULT TO 128. BYTE TRANSFER CMP U.CNT(R5),R1 ; 128. BYTES LEFT TO TRANSFER? BHIS 10$ ; YES MOV U.CNT(R5),R1 ; NO, GET RESIDUAL COUNT 10$: MOV R1,I.PRM+12(R3) ; STORE BYTES TO TRANSFER MOV U.BUF(R5),@KISR6 ; SET MAPPING REGISTER RETURN ; .END